#define BLINKER_WIFI           //wifi设备
#define BLINKER_MIOT_LIGHT     //小爱灯设备,用于小爱音箱绑定识别设备类型,这个不加,同步不出来设备
#define BLINKER_APCONFIG       //ApConfig设备在未配网状态以AP形式存在，APP扫描到设备，会连接上并给予目标ssid和密码，设备收到后，即会去连接目标ssid
#define BLINKER_BUTTON         //长按按钮触发设备重置功能
#define BLINKER_BUTTON_PIN D3  //按键引脚为D3
//
#define EEPROM_OPERAT_MAX_ADDR 4096  //申请操作到的最大地址addr
//掉电保存
#define EEPROM_LAST_R_ADDR 2432      //颜色亮度储存首地址
#define EEPROM_LAST_G_ADDR EEPROM_LAST_R_ADDR + 1
#define EEPROM_LAST_B_ADDR EEPROM_LAST_G_ADDR + 1
#define EEPROM_LAST_BRIGHT_ADDR EEPROM_LAST_B_ADDR + 1
#define EEPROM_LAST_SPEED_ADDR EEPROM_LAST_BRIGHT_ADDR + 1
#define EEPROM_LAST_MODE_ADDR EEPROM_LAST_SPEED_ADDR + 1
#define EEPROM_COLOR_TEMPERATURE_ADDR EEPROM_LAST_MODE_ADDR + 1
//最爱模式保存
#define EEPROM_LOVE_R_ADDR 2500      //最爱模式颜色亮度储存首地址
#define EEPROM_LOVE_G_ADDR EEPROM_LOVE_R_ADDR + 1
#define EEPROM_LOVE_B_ADDR EEPROM_LOVE_G_ADDR + 1
#define EEPROM_LOVE_BRIGHT_ADDR EEPROM_LOVE_B_ADDR + 1
#define EEPROM_LOVE_SPEED_ADDR EEPROM_LOVE_BRIGHT_ADDR + 1
#define EEPROM_LOVE_MODE_ADDR EEPROM_LOVE_SPEED_ADDR + 1

#include <Blinker.h>  //blinker库
#include "OneButton.h"
#include <EEPROM.h>
#include <Ticker.h>
#include <ArduinoOTA.h>
#include <WS2812FX.h>//灯条库

#define readHist  //上电后会读取上次存r的模式-亮度-颜色-速度
//灯带IO口
#define PIN D8
//灯个数
#define NUM_LEDS 60
//亮度
#define BRIGHTNESS 255

WS2812FX ws2812fx = WS2812FX(NUM_LEDS, PIN, NEO_RGB + NEO_KHZ800);

//char auth[] = "ad6284c9ac51";  //创建设备时的密钥
char auth[] = "2898e265fc6c"; 
//char ssid[] = "Y1415";         //wifi名
//char pswd[] = "y14151415";     //wifi密码

bool wsState;                           //开关状态
uint8_t wsMode = BLINKER_CMD_MIOT_DAY;  //模式初始定义为日光模式
int Mode = 0;                           //初始模式  温馨提示：固定颜色为模式0
int Speed = 10;                        //灯效节奏,初始速度  由于存储设置限制，实际时间为10倍数 毫秒
uint8_t colorW = 127;                   //初始亮度
uint8_t colorR = 255;                   //初始颜色RGB
uint8_t colorG = 255;
uint8_t colorB = 255;
int32_t cct = 0;  //发送用户需要的滑动条数值及设置的颜色到APP

// 闪烁时间间隔(秒)
//const int blinkInterval = 2;

// 新建组件对象
BlinkerButton Button_on("btn-1");    //app中按键的ID
BlinkerButton Button_Save("btn-2");  //app中按键的ID
BlinkerButton Button_Read("btn-3");
BlinkerRGB RGB1("RGB");                                     //颜色选择器的ID
BlinkerSlider Slider_ColorTemperature("ColorTemperature");  //色温
BlinkerSlider Slider_Mode("Mode");
BlinkerSlider Slider_Speed("Speed");
BlinkerText modeSaved("savedMode");
BlinkerText modeName("ModeName");
BlinkerText runTime("runTime");
BlinkerText IPaddr("IPaddress");

// button trigged when pin input level is LOW
OneButton button(BLINKER_BUTTON_PIN, true);
//Ticker ticker;

//保存颜色亮度值
void color_bright_save(int addr) {

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  EEPROM.write(addr, colorR);      //给EEPROM 写入值掉电保存
  EEPROM.write(EEPROM_LAST_G_ADDR, colorG);
  EEPROM.write(EEPROM_LAST_B_ADDR, colorB);
  EEPROM.write(EEPROM_LAST_BRIGHT_ADDR, colorW);
  EEPROM.commit();  //保存更改的数据
}

//保存色温值
void color_temperature_save(int addr, int32_t value) {

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  EEPROM.write(addr, value);
  EEPROM.commit();  //保存更改的数据
}

//保存模式
void mode_save(int addr, int r_mode) {

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  EEPROM.write(addr, r_mode);            //给EEPROM 写入值掉电保存
  EEPROM.commit();                       //保存更改的数据
}

//保存亮度模式
void bright_mode_save(int addr, int b_mode) {

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  EEPROM.write(addr, b_mode);            //给EEPROM 写入值掉电保存
  EEPROM.commit();                       //保存更改的数据
}

//保存速度
void speed_save(int addr, int s_mode) {

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  EEPROM.write(addr, s_mode);            //给EEPROM 写入值掉电保存
  EEPROM.commit();                       //保存更改的数据
}

// 心跳包函数
void heartbeat() {
  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址EEPROM_OPERAT_MAX_ADDR
  RGB1.print(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR),
             EEPROM.read(EEPROM_LAST_B_ADDR), EEPROM.read(EEPROM_LAST_BRIGHT_ADDR));  //上传RGB亮度信息
  String IPADDRESS = WiFi.localIP().toString();
  IPaddr.print(IPADDRESS);
  Slider_ColorTemperature.print(cct);  //发送用户需要的滑动条数值及设置的颜色到APP
}


// 按下按键即会执行该函数
void on_callback(const String& state) {
  BLINKER_LOG("get button state: ", state);
  if (state == "on") {
ws2812fx.setPixelColor(NUM_LEDS,colorR,colorG,colorB);
ws2812fx.setBrightness(colorW);
    digitalWrite(LED_BUILTIN, LOW);
    Button_on.print("on");
  } else if (state == "off") {
ws2812fx.setBrightness(0);

    digitalWrite(LED_BUILTIN, HIGH);
    Button_on.print("off");
  }
  Blinker.vibrate();
}

void save_callback(const String& state) {

  BLINKER_LOG("get button state: ", state);

  if (state == BLINKER_CMD_BUTTON_TAP) {
    EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);
    BLINKER_LOG("存储!");
    EEPROM.write(EEPROM_LOVE_R_ADDR, int(colorR));
    delay(50);
    EEPROM.write(EEPROM_LOVE_G_ADDR, int(colorG));
    delay(50);
    EEPROM.write(EEPROM_LOVE_B_ADDR, int(colorB));
    delay(50);
    EEPROM.write(EEPROM_LOVE_BRIGHT_ADDR, int(colorW));
    delay(50);
    EEPROM.write(EEPROM_LOVE_SPEED_ADDR, int(Speed));
    delay(50);
    EEPROM.write(EEPROM_LOVE_MODE_ADDR, int(Mode));
    delay(50);
    EEPROM.commit();
    if (EEPROM.commit()) {
      Serial.println("模式存储成功！");
      modeSaved.print("已存储模式", String(ws2812fx.getModeName(Mode)));
      Blinker.vibrate();
    } else {
      Serial.println("模式存储失败！");
    }
  }
}

void read_callback(const String& state) {

  BLINKER_LOG("get button state: ", state);

  if (state == BLINKER_CMD_BUTTON_TAP) {
    EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);
    BLINKER_LOG("读取!");

    colorR = EEPROM.read(EEPROM_LOVE_R_ADDR);
    colorG = EEPROM.read(EEPROM_LOVE_G_ADDR);
    colorB = EEPROM.read(EEPROM_LOVE_B_ADDR);
    colorW = EEPROM.read(EEPROM_LOVE_BRIGHT_ADDR);
    Speed = EEPROM.read(EEPROM_LOVE_SPEED_ADDR);
    Mode = EEPROM.read(EEPROM_LOVE_MODE_ADDR);
    Serial.println(colorR);
    Serial.println(colorG);
    Serial.println(colorB);
    Serial.println(colorW);
    Serial.println(Speed);
    Serial.println(Mode);
    ws2812fx.setPixelColor(NUM_LEDS,colorR, colorG, colorB);
    ws2812fx.setBrightness(colorW);
  ws2812fx.setSpeed(Speed * 100);
  ws2812fx.setMode(Mode);
RGB1.print(colorR, colorG, colorB, colorW);
    RGB1.brightness(colorW);
    Blinker.vibrate();
  }
}

//颜色选择器,根据颜色选择器选择的颜色改变RGB灯条
void rgb1_callback(uint8_t r_value, uint8_t g_value, uint8_t b_value, uint8_t bright_value) {
  digitalWrite(LED_BUILTIN, LOW);
  BLINKER_LOG("R value: ", r_value);
  BLINKER_LOG("G value: ", g_value);
  BLINKER_LOG("B value: ", b_value);
  BLINKER_LOG("Rrightness value: ", bright_value);

  colorR = r_value;
  colorG = g_value;
  colorB = b_value;
  colorW = bright_value;
  ws2812fx.setBrightness(colorW);
  ws2812fx.setPixelColor(NUM_LEDS,colorR, colorG, colorB);

//   RGB1.print(colorR,colorG,colorB,colorW);   //上传RGB亮度信息
color_bright_save(EEPROM_LAST_R_ADDR);
  String IPADDRESS = WiFi.localIP().toString();
  IPaddr.print(IPADDRESS);

  digitalWrite(LED_BUILTIN, HIGH);
}

//APP 色温滑动条设置回调
void Slider_ColorTemperature_callback(int32_t value) {

   BLINKER_LOG("get slider value: ", value);
  Color_temperature_conversion(value, &colorR, &colorG, &colorB);  //色温转RGB
ws2812fx.setBrightness(colorW);
  ws2812fx.setPixelColor(NUM_LEDS,colorR, colorG, colorB);

  color_temperature_save(EEPROM_COLOR_TEMPERATURE_ADDR, value);             //保存色温值
  RGB1.print(colorR, colorG, colorB, colorW);  //上传RGB亮度信息
  cct = value;
  //Slider_ColorTemperature.print(cct);  //发送用户需要的滑动条数值及设置的颜色到APP
}

void Mode_callback(int32_t value) {

  BLINKER_LOG("模式切换: ", value);
  Mode = int(value);
  ws2812fx.setMode(Mode);
  Slider_Mode.print(Mode);
  Serial.println(ws2812fx.getModeName(Mode));
  modeName.print("当前模式", String(ws2812fx.getModeName(Mode)));
  String IPADDRESS = WiFi.localIP().toString();
  IPaddr.print(IPADDRESS);
}

void Speed_callback(int32_t value) {
  BLINKER_LOG("速度调整: ", value);
  Speed = int(value);
  ws2812fx.setSpeed(Speed * 100);
  Slider_Speed.print(Speed);
  speed_save(EEPROM_LAST_SPEED_ADDR,Speed);
}


void dataRead(const String& data) {
  String IPADDRESS = WiFi.localIP().toString();
  IPaddr.print(IPADDRESS);
}

//小爱电源控制回调函数,在小爱训练里面添加开关灯时,会进入到这里
void miotPowerState(const String& state) {
  BLINKER_LOG("need set power state: ", state);

  if (state == BLINKER_CMD_OFF) {  //如果语音接收到是关闭灯
    digitalWrite(LED_BUILTIN, HIGH);

    EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址EEPROM_OPERAT_MAX_ADDR
    // SET_RGB(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR),
    //         EEPROM.read(EEPROM_LAST_B_ADDR), 0);

    ws2812fx.setBrightness(0);
    BlinkerMIOT.powerState("off");
    wsState = false;  //返回数据到小爱,否则小爱会报错
  } 
  else if (state == BLINKER_CMD_ON) {
    digitalWrite(LED_BUILTIN, LOW);

    EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址EEPROM_OPERAT_MAX_ADDR
  //  SET_RGB(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR),
   //         EEPROM.read(EEPROM_LAST_B_ADDR), 255);

    if (colorW == 0) ws2812fx.setBrightness(127);
    BlinkerMIOT.powerState("on");
    wsState = true;
  }
  BlinkerMIOT.print();
}
//小爱颜色控制回调函数,对小爱说把灯调成x色,就会到这里来执行
void miotColor(int32_t color) {
  BLINKER_LOG("need set color: ", color);
  colorR = color >> 16 & 0xFF;
  colorG = color >> 8 & 0xFF;
  colorB = color & 0xFF;
BLINKER_LOG("colorR: ", colorR, ", colorG: ", colorG, ", colorB: ", colorB, ", colorW: ", colorW);

  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);  //申请操作到地址addr
  //SET_RGB(colorR, colorG, colorB, EEPROM.read(EEPROM_LAST_BRIGHT_ADDR));
  
ws2812fx.setPixelColor(NUM_LEDS,colorR, colorG, colorB);
  ws2812fx.setMode(0);//语音调整颜色固定色 0
  RGB1.print(colorR, colorG, colorB);


  BlinkerMIOT.color(color);
  BlinkerMIOT.print();
}
//改变灯条亮度,对小爱说把灯的亮度调到百分之xx就是进到这里
void miotBright(const String& bright) {
  BLINKER_LOG("need set brightness: ", bright);

  colorW = bright.toInt();

  BLINKER_LOG("now set brightness: ", colorW);
   ws2812fx.setBrightness(map(colorW, 0, 100, 0, 255));
  RGB1.brightness(colorW);
  bright_mode_save(EEPROM_LAST_BRIGHT_ADDR,colorW);
  //pixels.setBrightness(colorW * 15 / 10 + 105);
  //因为函数设置的亮度是0-255,小爱接口的是1-100
  //pixels.setBrightness(map(colorW, 0, 100, 0, 255));
  //pixels.show();
  BlinkerMIOT.brightness(colorW);
  BlinkerMIOT.print();
}
//小爱色温的控制函数
void miotColoTemp(int32_t colorTemp) {
  BLINKER_LOG("need set colorTemperature: ", colorTemp);
  Slider_ColorTemperature_callback(colorTemp);
  BlinkerMIOT.colorTemp(colorTemp);
  BlinkerMIOT.print();
}
//当小爱同学向设备发起控制, 设备端需要有对应控制处理函数
void miotQuery(int32_t queryCode) {
  BLINKER_LOG("MIOT Query codes: ", queryCode);
  switch (queryCode) {
    case BLINKER_CMD_QUERY_ALL_NUMBER:  //所有状态
      BLINKER_LOG("MIOT Query All");
      BlinkerMIOT.powerState(wsState ? "on" : "off");
      BlinkerMIOT.color(ws2812fx.Color(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR), EEPROM.read(EEPROM_LAST_B_ADDR)));
      BlinkerMIOT.mode(Mode);
      BlinkerMIOT.colorTemp(EEPROM_COLOR_TEMPERATURE_ADDR);
      BlinkerMIOT.brightness(EEPROM_LAST_BRIGHT_ADDR);
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:  //电源状态
      BLINKER_LOG("MIOT Query Power State");
      BlinkerMIOT.powerState(wsState ? "on" : "off");
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_COLOR_NUMBER:  //颜色状态
      BLINKER_LOG("MIOT Query Color");
      BlinkerMIOT.color(ws2812fx.Color(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR), EEPROM.read(EEPROM_LAST_B_ADDR)));
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_MODE_NUMBER:  //模式状态
      BLINKER_LOG("MIOT Query Mode");
      BlinkerMIOT.mode(Mode);
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_COLORTEMP_NUMBER:  //色温状态
      BLINKER_LOG("MIOT Query ColorTemperature");
      BlinkerMIOT.colorTemp(EEPROM_COLOR_TEMPERATURE_ADDR);
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_BRIGHTNESS_NUMBER:  //亮度状态
      BLINKER_LOG("MIOT Query Brightness");
      BlinkerMIOT.brightness(EEPROM_LAST_BRIGHT_ADDR);
      BlinkerMIOT.print();
      break;
    default:
      BlinkerMIOT.powerState(wsState ? "on" : "off");
      BlinkerMIOT.color(ws2812fx.Color(EEPROM.read(EEPROM_LAST_R_ADDR), EEPROM.read(EEPROM_LAST_G_ADDR), EEPROM.read(EEPROM_LAST_B_ADDR)));
      BlinkerMIOT.mode(Mode);
      BlinkerMIOT.colorTemp(EEPROM_COLOR_TEMPERATURE_ADDR);
      BlinkerMIOT.brightness(EEPROM_LAST_BRIGHT_ADDR);
      BlinkerMIOT.print();
      break;
  }
}

//小爱切换模式,对小爱说把灯调到XX模式,就会执行相应的操作
void miotMode(uint8_t mode) {
  BLINKER_LOG("need set mode: ", mode);
  if (mode == BLINKER_CMD_MIOT_DAY) {
    ///日光模式
    Mode = 10;
  } else if (mode == BLINKER_CMD_MIOT_NIGHT) {
    //夜光模式
    Mode = 20;
  } else if (mode == BLINKER_CMD_MIOT_COLOR) {
    //彩光
    Mode = 0;
  } else if (mode == BLINKER_CMD_MIOT_WARMTH) {
    // 温馨
    Mode = 2;
  } else if (mode == BLINKER_CMD_MIOT_TV) {
    // 电视模式
    Mode = 11;
  } else if (mode == BLINKER_CMD_MIOT_READING) {
    // 阅读模式
    Mode = 43;
  } else if (mode == BLINKER_CMD_MIOT_COMPUTER) {
    // 电脑模式
    Mode = 12;
  }
  ws2812fx.setMode(Mode);
  wsMode = mode;

  Slider_Mode.print(Mode);
  modeName.print(ws2812fx.getModeName(Mode));

  BlinkerMIOT.mode(mode);
  BlinkerMIOT.print();
}


//重置网络执行函数
void deviceReset() {
  Blinker.vibrate();
  Blinker.reset();
}

// 在Tinker对象控制下，此函数将会定时执行。
void tickerCount() {
  //digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}



//初始化
void setup() {
  // 初始化串口
  Serial.begin(115200);
  BLINKER_DEBUG.stream(Serial);
  //BLINKER_DEBUG.debugAll();

#ifdef readHist
  EEPROM.begin(EEPROM_OPERAT_MAX_ADDR);
  Serial.println("已开启历史模式功能，读取历史设置数据中...");
  if (EEPROM.read(2505) != 255) {
    colorR = EEPROM.read(EEPROM_LAST_R_ADDR);
    delay(10);
    colorG = EEPROM.read(EEPROM_LAST_G_ADDR);
    delay(10);
    colorB = EEPROM.read(EEPROM_LAST_B_ADDR);
    delay(10);
    colorW = EEPROM.read(EEPROM_LAST_BRIGHT_ADDR);
    delay(10);
    Speed = EEPROM.read(EEPROM_LAST_SPEED_ADDR);
    delay(10);
    Mode = EEPROM.read(EEPROM_LAST_MODE_ADDR);
    delay(10);
    for (int i = 0; i < 6; i++) {
      Serial.println(EEPROM.read(i + 2500));
    }
  }
  if (EEPROM.read(2505) == 255) {
    Serial.println("读取存储模式失败...");
  }

#endif

  pinMode(LED_BUILTIN, OUTPUT);
  //ticker.attach(blinkInterval, tickerCount);  // 设置Ticker对象

  // 初始化blinker
  //Blinker.begin(auth, ssid, pswd);
  Blinker.begin(auth);
  Serial.println('\n');            // WiFi连接成功后
  Serial.print("Connected to ");   // NodeMCU将通过串口监视器输出。
  Serial.println(WiFi.SSID());     // 连接的WiFI名称
  Serial.print("IP address:\t");   // 以及
  Serial.println(WiFi.localIP());  // NodeMCU的IP地址


  // OTA设置并启动
  // ArduinoOTA.setHostname("MAX_Robin");
  // ArduinoOTA.setPassword("04300621");
  // ArduinoOTA.begin();
  // Serial.println("OTA ready");

  //点灯科技APP控件回调绑定
  Button_on.attach(on_callback);
  Button_Save.attach(save_callback);
  Button_Read.attach(read_callback);
  RGB1.attach(rgb1_callback);
  Slider_ColorTemperature.attach(Slider_ColorTemperature_callback);
  Slider_Mode.attach(Mode_callback);
  Slider_Speed.attach(Speed_callback);

  Blinker.attachData(dataRead);  //收到APP发来的数据时会调用对应的回调函数

  // 注册心跳包函数
  Blinker.attachHeartbeat(heartbeat);
  //小爱语音回调函数
  BlinkerMIOT.attachPowerState(miotPowerState);      //这段代码一定要加，不加小爱同学控制不了,务必在回调函数中反馈该
  BlinkerMIOT.attachColor(miotColor);                //颜色回调函数
  BlinkerMIOT.attachBrightness(miotBright);          //亮度
  BlinkerMIOT.attachColorTemperature(miotColoTemp);  //色温
  BlinkerMIOT.attachQuery(miotQuery);                //反馈该控制状态
  BlinkerMIOT.attachMode(miotMode);                  //模式



  ws2812fx.init();
  ws2812fx.setBrightness(colorW);  //?
  ws2812fx.setPixelColor(NUM_LEDS,colorR,colorG,colorB);
  ws2812fx.setSpeed(Speed * 100);              //?
  ws2812fx.setMode(Mode);
  ws2812fx.start();
  Serial.println("模式：");
  Serial.println(ws2812fx.getModeName(Mode));

  //反馈给app
  // IPaddr.print(WiFi.localIP().toString());
  // RGB1.brightness(colorW);  //?
  // RGB1.print(colorR, colorG, colorB);                 //?
  // Slider_Mode.print(Mode);
  // modeName.print(ws2812fx.getModeName(Mode));
  // modeSaved.print(Mode);
  // Slider_Speed.print(Speed);


  //长按按钮触发设备重置功能
  button.attachLongPressStop(deviceReset);
}

void loop() {
  button.tick();
//  ArduinoOTA.handle();
  Blinker.run();
  ws2812fx.service();
}

/*******************************************************************************
*@ Description    将给定的色温值(tmpKelvin)转换为RGB颜色值  
*@ Input          :<tmpKelvin>输入的色温值（[1000,40000]单位：K，开尔文）
*@ Output         :
*@ Return         :
*******************************************************************************/
int Color_temperature_conversion(unsigned int tmpKelvin, unsigned char* r, unsigned char* g, unsigned char* b) {

  static double tmpCalc = 0;

  if (tmpKelvin < 1000) {
    tmpKelvin = 1000;
  }
  if (tmpKelvin > 40000) {
    tmpKelvin = 40000;
  }
  tmpKelvin = tmpKelvin / 100;

  /*----#red----------------------------------------------------------------------------*/
  if (tmpKelvin <= 66) {
    *r = 255;
  } else {
    tmpCalc = tmpKelvin - 60;
    tmpCalc = 329.698727446 * (pow(tmpCalc, -0.1332047592));
    *r = tmpCalc;
    if (*r < 0) {
      *r = 0;
    }

    if (*r > 255) {
      *r = 255;
    }
  }

  /*----#green----------------------------------------------------------------------------*/
  if (tmpKelvin <= 66) {
    tmpCalc = tmpKelvin;
    tmpCalc = 99.4708025861 * log(tmpCalc) - 161.1195681661;
    *g = tmpCalc;

    if (*g < 0) {
      *g = 0;
    }
    if (*g > 255) {
      *g = 255;
    }
  } else {
    tmpCalc = tmpKelvin - 60;
    tmpCalc = 288.1221695283 * (pow(tmpCalc, -0.0755148492));
    *g = tmpCalc;

    if (*g < 0) {
      *g = 0;
    }
    if (*g > 255) {
      *g = 255;
    }
  }

  /*----#blue----------------------------------------------------------------------------*/
  if (tmpKelvin >= 66) {
    *b = 255;
  } else if (tmpKelvin <= 19) {
    *b = 0;
  } else {
    tmpCalc = tmpKelvin - 10;
    tmpCalc = 138.5177312231 * log(tmpCalc) - 305.0447927307;
    *b = tmpCalc;
    if (*b < 0) {
      *b = 0;
    }
    if (*b > 255) {
      *b = 255;
    }
  }
  return 0;
}

//72种模式
/*
#define FX_MODE_STATIC                   0
#define FX_MODE_BLINK                    1
#define FX_MODE_BREATH                   2
#define FX_MODE_COLOR_WIPE               3
#define FX_MODE_COLOR_WIPE_INV           4 
#define FX_MODE_COLOR_WIPE_REV           5
#define FX_MODE_COLOR_WIPE_REV_INV       6
#define FX_MODE_COLOR_WIPE_RANDOM        7
#define FX_MODE_RANDOM_COLOR             8
#define FX_MODE_SINGLE_DYNAMIC           9
#define FX_MODE_MULTI_DYNAMIC           10
#define FX_MODE_RAINBOW                 11
#define FX_MODE_RAINBOW_CYCLE           12
#define FX_MODE_SCAN                    13
#define FX_MODE_DUAL_SCAN               14
#define FX_MODE_FADE                    15
#define FX_MODE_THEATER_CHASE           16
#define FX_MODE_THEATER_CHASE_RAINBOW   17
#define FX_MODE_RUNNING_LIGHTS          18
#define FX_MODE_TWINKLE                 19
#define FX_MODE_TWINKLE_RANDOM          20
#define FX_MODE_TWINKLE_FADE            21
#define FX_MODE_TWINKLE_FADE_RANDOM     22
#define FX_MODE_SPARKLE                 23
#define FX_MODE_FLASH_SPARKLE           24
#define FX_MODE_HYPER_SPARKLE           25
#define FX_MODE_STROBE                  26
#define FX_MODE_STROBE_RAINBOW          27
#define FX_MODE_MULTI_STROBE            28
#define FX_MODE_BLINK_RAINBOW           29
#define FX_MODE_CHASE_WHITE             30
#define FX_MODE_CHASE_COLOR             31
#define FX_MODE_CHASE_RANDOM            32
#define FX_MODE_CHASE_RAINBOW           33
#define FX_MODE_CHASE_FLASH             34
#define FX_MODE_CHASE_FLASH_RANDOM      35
#define FX_MODE_CHASE_RAINBOW_WHITE     36
#define FX_MODE_CHASE_BLACKOUT          37
#define FX_MODE_CHASE_BLACKOUT_RAINBOW  38
#define FX_MODE_COLOR_SWEEP_RANDOM      39
#define FX_MODE_RUNNING_COLOR           40
#define FX_MODE_RUNNING_RED_BLUE        41
#define FX_MODE_RUNNING_RANDOM          42
#define FX_MODE_LARSON_SCANNER          43
#define FX_MODE_COMET                   44
#define FX_MODE_FIREWORKS               45
#define FX_MODE_FIREWORKS_RANDOM        46
#define FX_MODE_MERRY_CHRISTMAS         47
#define FX_MODE_FIRE_FLICKER            48
#define FX_MODE_FIRE_FLICKER_SOFT       49
#define FX_MODE_FIRE_FLICKER_INTENSE    50
#define FX_MODE_CIRCUS_COMBUSTUS        51
#define FX_MODE_HALLOWEEN               52
#define FX_MODE_BICOLOR_CHASE           53
#define FX_MODE_TRICOLOR_CHASE          54
#define FX_MODE_TWINKLEFOX              55
#define FX_MODE_RAIN                    56
#define FX_MODE_BLOCK_DISSOLVE          57
#define FX_MODE_ICU                     58
#define FX_MODE_DUAL_LARSON             59
#define FX_MODE_RUNNING_RANDOM2         60
#define FX_MODE_FILLER_UP               61
#define FX_MODE_RAINBOW_LARSON          62
#define FX_MODE_RAINBOW_FIREWORKS       63
#define FX_MODE_TRIFADE                 64
#define FX_MODE_VU_METER                65
#define FX_MODE_HEARTBEAT               66
#define FX_MODE_BITS                    67
#define FX_MODE_MULTI_COMET             68
#define FX_MODE_FLIPBOOK                69
#define FX_MODE_POPCORN                 70
#define FX_MODE_OSCILLATOR              71
*/
